home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / Flip / turboc.c < prev    next >
C/C++ Source or Header  |  1995-06-12  |  10KB  |  326 lines

  1. /* ::[[ @(#) turboc.c 1.6 89/07/02 00:19:31 ]]:: */
  2. #ifndef LINT
  3. static char sccsid[]="::[[ @(#) turboc.c 1.6 89/07/02 00:19:31 ]]::";
  4. #endif
  5.  
  6. /*
  7. Copyright 1989 Rahul Dhesi, All rights reserved.
  8.  
  9. This file is used only for MS-DOS & Turbo C.
  10. */
  11.  
  12. /*
  13. Checksum: 3933529970      (check or update this with "brik")
  14. */
  15.  
  16. /*
  17. nextfile() is a general wildcard expansion function that may be used
  18. with other programs.  Usage instructions are below.  It does not
  19. simply expand wildcards in an entire argument list.  Instead, it is
  20. called in a loop as described below, and returns one matching
  21. filename each time it is called.
  22.  
  23. These functions are for the SMALL MEMORY MODEL ONLY.
  24. */
  25.  
  26. extern unsigned _stklen = 10000;
  27.  
  28. #include "assert.h"
  29. #include "flip.h"
  30.  
  31. #define  FMAX  2        /* Number of different filename patterns */
  32. #define  PATHSIZE 200   /* Size of MS-DOS pathname */
  33. #define  NULL  0
  34.  
  35. #ifdef ANSIPROTO
  36. char *strtcpy (char *, char *);
  37. int strlen (char *);
  38. char *strcpy (char *, char *);
  39. #endif
  40.  
  41.  
  42. /* Structure definitions for MS-DOS software interrupt intdos() */
  43.  
  44. struct WORD_REGISTERS {
  45.    unsigned int ax, bx, cx, dx, si, di, carry, flags;
  46. };
  47.  
  48. /* byte registers */
  49.  
  50. struct BYTE_REGISTERS {
  51.    unsigned char al, ah, bl, bh, cl, ch, dl, dh;
  52. };
  53.  
  54. union REGS {
  55.    struct WORD_REGISTERS x;
  56.    struct BYTE_REGISTERS h;
  57. };
  58.  
  59. int intdos (union REGS *, union REGS *);
  60.  
  61. /*
  62. format of disk transfer address after MS-DOS calls FindFirst and
  63. FindNext
  64. */
  65. struct dta_t {
  66.    char junk[22];
  67.    int time;
  68.    int date;
  69.    long size;
  70.    char fname[13];
  71.    char just_in_case[4];   /* in case MS-DOS writes too much */
  72. };
  73.  
  74. void setdta (struct dta_t *);
  75. void fcbpath (struct dta_t *, char *, char *);
  76.  
  77. /*******************/
  78. /*
  79. nextfile() returns the name of the next source file matching a filespec.
  80.  
  81. INPUT
  82.    what: A flag specifying what to do.  If "what" is 0, nextfile()
  83.       initializes itself.  If "what" is 1, nextfile() returns the next
  84.       matching filename.
  85.    filespec:  The filespec, usually containing wildcard characters, that
  86.       specifies which files are needed.  If "what" is 0, filespec must be
  87.       the filespec for which matching filenames are needed.  If "what" is 1,
  88.       nextfile() does not use "filespec" and "filespec" should be NULL to
  89.       avoid an assertion error during debugging.
  90.    fileset:  nextfile() can keep track of more than one set of filespecs.
  91.       The fileset specifies which filespec is being matched and therefore
  92.       which set of files is being considered.  "fileset" can be in the
  93.       range 0:FMAX.  Initialization of one fileset does not affect the
  94.       other filesets.
  95.  
  96. OUTPUT
  97.    IF what == 0 THEN
  98.       return value is NULL
  99.    ELSE IF what == 1 THEN
  100.       IF a matching filename is found THEN
  101.          return value is pointer to matching filename including supplied path
  102.       ELSE
  103.          IF at least one file matched previously but no more match THEN
  104.             return value is NULL
  105.          ELSE IF supplied filespec never matched any filename THEN
  106.             IF this is the first call with what == 1 THEN
  107.                return value is pointer to original filespec
  108.             ELSE
  109.                return value is NULL
  110.             END IF
  111.          END IF
  112.       END IF
  113.    END IF
  114.  
  115. NOTE
  116.  
  117.    Initialization done when "what"=0 is not dependent on the correctness
  118.    of the supplied filespec but simply initializes internal variables
  119.    and makes a local copy of the supplied filespec.  If the supplied
  120.    filespec was illegal, the only effect is that the first time that
  121.    nextfile() is called with "what"=1, it will return the original
  122.    filespec instead of a matching filename.  That the filespec was
  123.    illegal will become obvious when the caller attempts to open the
  124.    returned filename for input/output and the open attempt fails.
  125.  
  126. USAGE HINTS
  127.  
  128. nextfile() can be used in the following manner:
  129.  
  130.       char *filespec;                  -- will point to filespec
  131.       char *this_file;                 -- will point to matching filename
  132.       filespec = parse_command_line(); -- may contain wildcards
  133.       FILE *stream;
  134.  
  135.       nextfile (0, filespec, 0);          -- initialize fileset 0
  136.       while ((this_file = nextfile(1, (char *) NULL, 0)) != NULL) {
  137.          stream = fopen (this_file, "whatever");
  138.          if (stream == NULL)
  139.             printf ("could not open %s\n", this_file);
  140.          else
  141.             perform_operations (stream);
  142.       }
  143. */
  144.  
  145. char *nextfile (what, filespec, fileset)
  146. int what;                        /* whether to initialize or match      */
  147. register char *filespec;         /* filespec to match if initializing   */
  148. register int fileset;            /* which set of files                  */
  149. {
  150.    static struct dta_t new_dta [FMAX+1];     /* our own private dta        */
  151.    static int first_time [FMAX+1];
  152.    static char pathholder [FMAX+1][PATHSIZE]; /* holds a pathname to return */
  153.    static char saved_fspec [FMAX+1][PATHSIZE];/* our own copy of filespec   */
  154.    union REGS regs;
  155.  
  156.    assert(fileset >= 0 && fileset <= FMAX);
  157.    if (what == 0) {
  158.       assert(filespec != NULL);
  159.       strcpy (saved_fspec[fileset], filespec);  /* save the filespec */
  160.       first_time[fileset] = 1;
  161.       return ((char *) NULL);
  162.    }
  163.  
  164.    setdta (&new_dta[fileset]);   /* set new dta -- our very own */
  165.    assert(what == 1);
  166.    assert(filespec == NULL);
  167.    assert(first_time[fileset] == 0 || first_time[fileset] == 1);
  168.  
  169.    if (first_time[fileset]) {             /* first time -- initialize etc. */
  170.       /* find first matching file */
  171.       regs.h.ah = 0x4e;                   /* FindFirst MS-DOS call    */
  172.       regs.x.dx = (unsigned int) saved_fspec[fileset]; /* filespec to match */
  173.       regs.x.cx = 0;                      /* search attributes       */
  174.       intdos (®s, ®s);
  175.    } else {
  176.       /* find next matching file */
  177.       regs.h.ah = 0x4f;                   /* FindNext MS-DOS call     */
  178.       intdos (®s, ®s);
  179.    }
  180.  
  181.    if (regs.x.carry != 0) {            /* if error status                  */
  182.       if (first_time[fileset]) {       /*   if file never matched then     */
  183.          first_time[fileset] = 0;
  184.          return (saved_fspec[fileset]);/*      return original filespec    */
  185.       } else {                         /*   else                           */
  186.          first_time[fileset] = 0;      /*                                  */
  187.          return ((char *) NULL);         /*      return (NULL) for no more   */
  188.       }
  189.    } else {                                        /* a file matched */
  190.       first_time[fileset] = 0;
  191.       /* add path info  */
  192.       fcbpath (&new_dta[fileset], saved_fspec[fileset], pathholder[fileset]);
  193.       return (pathholder[fileset]);                /* matching path  */
  194.    }
  195. } /* nextfile */
  196.  
  197. /*******************/
  198. /* This function sets the dta to a new dta */
  199. void setdta (dta)
  200. struct dta_t *dta;
  201. {
  202.    union REGS regs;
  203.    regs.h.ah = 0x1a;                /* SetDTA Call       */
  204.    regs.x.dx = (unsigned int) dta;  /* new DTA address   */
  205.    intdos (®s, ®s);
  206. }
  207.  
  208. /*******************/
  209. /*
  210. fcbpath() accepts a pointer to the Disk Transfer Area, a character
  211. pointer to a pathname that may contain wildcards, and a character
  212. pointer to a buffer.  It copies into the buffer the path prefix from
  213. the pathname and the filename prefix from the DTA so that it forms a
  214. complete path.
  215. */
  216.  
  217. void fcbpath (dta, old_path, new_path)
  218. struct dta_t *dta;
  219. char *old_path;
  220. register char *new_path;
  221. {
  222.    register int i;
  223.    int length, start_pos;
  224.  
  225.    strcpy(new_path, old_path);               /* copy the whole thing first */
  226.    length = strlen(new_path);
  227.    i = length - 1;                           /* i points to end of path */
  228.    while (i >= 0 && new_path[i] != '/' && new_path[i] != '\\' && new_path[i] != ':')
  229.       i--;
  230.    /* either we found a "/", "\", or ":", or we reached the beginning of
  231.       the name.  In any case, i points to the last character of the
  232.       path part. */
  233.    start_pos = i + 1;
  234.    for (i = 0; i < 13; i++)
  235.       new_path[start_pos+i] = dta->fname[i];
  236.    new_path[start_pos+13] = '\0';
  237. }
  238. /* -- END OF nextfile() and related functions -- */
  239.  
  240. /*
  241. For Turbo C, we implement MVFILE as a file copy to avoid wildcard
  242. expansion finding the same file again after a direct rename.  To
  243. avoid leaving a partially-written destination file, we trap ^C,
  244. and if it occurs, delete the dest file and quickly do just a simple
  245. rename to it.
  246. */
  247.  
  248. #define BLOCKSIZ  16384
  249. #include <fcntl.h>
  250. #include <sys/stat.h>
  251. #include <io.h>
  252. #include <signal.h>
  253.  
  254. void handler (int);        /* ^C handler */
  255. char  *xsrc, *xdest;       /* global for handler() */
  256. void (*oldsignal) (int);   /* global for handler() */
  257. int infd, outfd;           /* global for handler() */
  258. int brk_flag;              /* ms-dos break flag status */
  259. int getcbrk (void);
  260. int setcbrk (int);
  261.  
  262. int MVFILE (src, dest)
  263. char *src;
  264. char *dest;
  265. {
  266.    int retval;
  267.    char buf[BLOCKSIZ];
  268.  
  269.    retval = -1;               /* default error return */
  270.    xsrc = src;  xdest = dest; /* make visible to handler */
  271.  
  272.    oldsignal = signal (SIGINT, handler);
  273.    outfd = open (dest, O_CREAT|O_TRUNC|O_BINARY, S_IREAD|S_IWRITE);
  274.    if (outfd == -1)
  275.       goto erret;
  276.    infd = open (src, O_RDONLY|O_BINARY);
  277.    if (infd == -1) {
  278.       close (outfd);
  279.       goto erret;
  280.    }
  281.    while ((retval = read (infd, buf, BLOCKSIZ)) > 0) {
  282.       if (write (outfd, buf, retval) != retval) {
  283.          retval = -1;
  284.          goto done;
  285.       }
  286.    }
  287.  done: /* retval is zero on normal exit from loop, else nonzero */
  288.    close (infd); close (outfd);
  289.  
  290.    if (retval == 0) {
  291.       signal (SIGINT, oldsignal);      /* avoid race condition */
  292.       unlink (src);
  293.       return (retval);
  294.    }
  295. erret:
  296.    /* if error during read/write, do rename to avoid loss of dest file */
  297.    unlink (dest);
  298.    retval = rename (src, dest);
  299.    signal (SIGINT, oldsignal);
  300.    return (retval);
  301. }
  302.  
  303. void handler (int sig)
  304. {
  305.    signal (sig, SIG_IGN);
  306.    close (infd);  close (outfd);
  307.    unlink (xdest);
  308.    rename (xsrc, xdest);
  309.    signal (sig, oldsignal);
  310.    raise  (sig);                 /* original handler gets signal now */
  311. }
  312.  
  313. #include <conio.h>
  314. void brktst() { kbhit(); }      /* test for user interrupt */
  315.  
  316. void spec_init()
  317. {
  318.    brk_flag = getcbrk();
  319.    setcbrk (0);
  320. }
  321.  
  322. void spec_exit()
  323. {
  324.    setcbrk (brk_flag);
  325. }
  326.